package com.itgacl.magic4j.modules.comm.service.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.google.zxing.WriterException;
import com.itgacl.magic4j.libcommon.exception.Magic4jException;
import com.itgacl.magic4j.libcommon.util.DateUtils;
import com.itgacl.magic4j.libcommon.util.QrCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itgacl.magic4j.modules.comm.dto.CommQrcodeInfoDTO;
import com.itgacl.magic4j.modules.comm.vo.CommQrcodeInfoVo;
import com.itgacl.magic4j.modules.comm.converter.CommQrcodeInfoConverter;
import com.itgacl.magic4j.common.enums.ErrorCodeEnum;
import com.itgacl.magic4j.common.util.AssertUtil;
import com.itgacl.magic4j.common.validator.DataValidator;
import com.itgacl.magic4j.modules.comm.entity.CommQrcodeInfo;
import com.itgacl.magic4j.modules.comm.mapper.CommQrcodeInfoMapper;
import com.itgacl.magic4j.modules.comm.service.CommQrcodeInfoService;
import org.springframework.stereotype.Service;
import com.itgacl.magic4j.common.bean.PageData;
import com.itgacl.magic4j.common.bean.PageParam;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Classname CommQrcodeInfoServiceImpl
 * @Description CommQrcodeInfoService实现类
 * @Author Created by xudp (alias:孤傲苍狼) 290603672@qq.com
 * @Date 2021-03-05
 * @Version 1.0
 */
@Slf4j
@Service
public class CommQrcodeInfoServiceImpl extends ServiceImpl<CommQrcodeInfoMapper, CommQrcodeInfo> implements CommQrcodeInfoService {

    @Override
    public void create(CommQrcodeInfoDTO commQrcodeInfoDTO) {
        dataValidator.validate(commQrcodeInfoDTO);//业务处理校验
        CommQrcodeInfo commQrcodeInfo = CommQrcodeInfoConverter.build().entity(commQrcodeInfoDTO);//DTO转换成Entity
        try {
            String qrCodeImgUrl = QrCodeUtil.createQRCode(commQrcodeInfoDTO.getQrcodeText(), commQrcodeInfoDTO.getTopFont(), commQrcodeInfoDTO.getCenterFont(),commQrcodeInfoDTO.getBottomFont());
            if(StrUtil.isBlank(qrCodeImgUrl)){
               throw new Magic4jException("二维码生成失败");
            }
            commQrcodeInfo.setQrcodeUrl(qrCodeImgUrl);
            save(commQrcodeInfo);//保存
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            throw new Magic4jException("二维码生成出错");
        }
    }

    @Override
    public void update(CommQrcodeInfoDTO commQrcodeInfoDTO) {
        dataValidator.validate(commQrcodeInfoDTO);//业务处理校验
        CommQrcodeInfo commQrcodeInfo = CommQrcodeInfoConverter.build().entity(commQrcodeInfoDTO);//DTO转换成Entity
        try {
            String qrCodeImgUrl = QrCodeUtil.createQRCode(commQrcodeInfoDTO.getQrcodeText(), commQrcodeInfoDTO.getTopFont(), commQrcodeInfoDTO.getCenterFont(),commQrcodeInfoDTO.getBottomFont());
            if(StrUtil.isBlank(qrCodeImgUrl)){
                throw new Magic4jException("二维码生成失败");
            }
            commQrcodeInfo.setQrcodeUrl(qrCodeImgUrl);
            commQrcodeInfo.setCreateTime(LocalDateTime.now());
            updateById(commQrcodeInfo);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            throw new Magic4jException("二维码生成出错");
        }
    }
 
    @Override
    public void deleteById(Long id) {
        removeById(id);//逻辑删除
    }

    @Override
    public void deleteByIds(List<Long> idList) {
        removeByIds(idList);//逻辑删除
    }

    @Override
    public CommQrcodeInfoVo getCommQrcodeInfoById(Long id) {
        CommQrcodeInfo commQrcodeInfo = getById(id);
        AssertUtil.notNull(ErrorCodeEnum.DATA_NOT_EXIST,commQrcodeInfo);
        return CommQrcodeInfoConverter.build().vo(commQrcodeInfo);
    }

    @Override
    public void delete(QueryWrapper<CommQrcodeInfo> queryWrapper) {
        remove(queryWrapper);
    }

    @Override
    public void deleteAll() {
        remove(null);//全部删除(逻辑删除)
    }

    @Override
    public List<CommQrcodeInfoVo> getList(QueryWrapper<CommQrcodeInfo> queryWrapper) {
        List<CommQrcodeInfo> commQrcodeInfoList = list(queryWrapper);
        return CommQrcodeInfoConverter.build().listVO(commQrcodeInfoList);
    }

    @Override
    public PageData<CommQrcodeInfoVo> pageList(Page<CommQrcodeInfo> page, QueryWrapper<CommQrcodeInfo> queryWrapper) {
        IPage<CommQrcodeInfo> pageInfo = page(page,queryWrapper);//mybatisPlus分页查询
        IPage<CommQrcodeInfoVo> pageVO = CommQrcodeInfoConverter.build().pageVO(pageInfo);
        return PageData.build(pageVO);
    }

    @Override
    public PageData<CommQrcodeInfoVo> pageList(PageParam pageParam, QueryWrapper<CommQrcodeInfo> queryWrapper) {
        Page<CommQrcodeInfo> page = new Page<>(pageParam.getPageNum(),pageParam.getPageSize());
        return pageList(page,queryWrapper);
    }

    /**
     * 将二维码图片打包压缩下载
     * @param idList      id集合
     * @param response
     */
    @Override
    public void zipDownload(List<Long> idList, HttpServletResponse response) {
        //根据id查询二维码链接
        QueryWrapper<CommQrcodeInfo> queryWrapper = new QueryWrapper<>();
        if (CollectionUtil.isNotEmpty(idList)) {
            queryWrapper.in(CommQrcodeInfo.ID, idList);
        }
        List<CommQrcodeInfoVo> commQrcodeInfoVos = this.getList(queryWrapper);
        if(CollectionUtil.isNotEmpty(commQrcodeInfoVos)){
            //2.开始批量下载功能
            try {
                String nowTimeString = DateUtils.getCurrentTime();
                String downloadFilename = "二维码-" + nowTimeString + ".zip";//文件的名称
                downloadFilename = URLEncoder.encode(downloadFilename, "UTF-8");//转换中文否则可能会产生乱码
                response.setContentType("application/octet-stream");// 指明response的返回对象是文件流
                response.setHeader("Content-Disposition", "attachment;filename=" + downloadFilename);// 设置在下载框默认显示的文件名
                ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
                InputStream inputStream;
                for (CommQrcodeInfoVo qrcodeInfoVo : commQrcodeInfoVos) {
                    String qrcodeUrl = qrcodeInfoVo.getQrcodeUrl();
                    URL url = new URL(qrcodeUrl);
                    zos.putNextEntry(new ZipEntry(qrcodeUrl.substring(qrcodeUrl.lastIndexOf("/")+1)));
                    inputStream = url.openConnection().getInputStream();
                    byte[] buffer = new byte[1024];
                    int r;
                    while ((r = inputStream.read(buffer)) != -1) {
                        zos.write(buffer, 0, r);
                    }
                    inputStream.close();
                }
                zos.flush();
                zos.close();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }

    }

    @Override
    public void createQrcode(List<Long> idList) {
        //根据id查询二维码信息
        QueryWrapper<CommQrcodeInfo> queryWrapper = new QueryWrapper<>();
        if (CollectionUtil.isNotEmpty(idList)) {
            queryWrapper.in(CommQrcodeInfo.ID, idList);
        }
        List<CommQrcodeInfo> commQrcodeInfos = this.list(queryWrapper);
        for (CommQrcodeInfo qrcodeInfo : commQrcodeInfos) {
            try {
                String qrCodeImgUrl = QrCodeUtil.createQRCode(qrcodeInfo.getQrcodeText(), qrcodeInfo.getTopFont(), qrcodeInfo.getCenterFont(),qrcodeInfo.getBottomFont());
                qrcodeInfo.setQrcodeUrl(qrCodeImgUrl);
                qrcodeInfo.setCreateTime(LocalDateTime.now());
            } catch (Exception e) {
               log.error(e.getMessage(),e);
            }
        }
        updateBatchById(commQrcodeInfos);
    }

    /**
     * 数据校验器
     */
    private DataValidator<CommQrcodeInfoDTO> dataValidator = new DataValidator<CommQrcodeInfoDTO>(){

        /**
        * 数据合法性校验(非空、数据格式等)
        * @param data
        */
        @Override
        protected void validateData(CommQrcodeInfoDTO data) {
            //todo:在这里编写数据校验处理逻辑，如果校验不通过，抛出DataValidationException异常
            // throw new DataValidationException("校验不通过抛出的错误提示消息");
        }

        /**
         * 保存之前进行校验(例如：数据是否已存在校验)
         * @param data
         */
        @Override
        protected void beforeCreate(CommQrcodeInfoDTO data) {

        }

        /**
         * 更新之前进行校验(例如：数据是否已存在校验)
         * @param data
         */
        @Override
        protected void beforeUpdate(CommQrcodeInfoDTO data) {

        }
    };
}
